Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ISpanParsable on to GrainId #8565

Merged
merged 3 commits into from
Aug 3, 2023

Conversation

Romanx
Copy link
Contributor

@Romanx Romanx commented Aug 2, 2023

While working on a client library I noticed that GrainId was not ISpanParsable but it did have implementations for parsing from a string.

This adds the interface and makes the existing string parse methods conform with the IParsable interface too.

Adding as draft as I need to check if some unit tests need to be added for this.

Microsoft Reviewers: Open in CodeFlow

Copy link
Member

@gfoidl gfoidl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there tests that cover this?

src/Orleans.Core.Abstractions/IDs/GrainId.cs Show resolved Hide resolved
src/Orleans.Core.Abstractions/IDs/GrainId.cs Outdated Show resolved Hide resolved
src/Orleans.Core.Abstractions/IDs/GrainId.cs Outdated Show resolved Hide resolved
@Romanx Romanx force-pushed the feature/span-parsable-grain-ids branch from bb6c6f7 to 723cd7d Compare August 2, 2023 13:19
Copy link
Contributor Author

@Romanx Romanx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review @gfoidl. Made the changes suggested.

Currently this is in draft as I wanted to see if there was any tests for this functionality. It doesn't look like there is so adding some now.

src/Orleans.Core.Abstractions/IDs/GrainId.cs Show resolved Hide resolved
src/Orleans.Core.Abstractions/IDs/GrainId.cs Outdated Show resolved Hide resolved
src/Orleans.Core.Abstractions/IDs/GrainId.cs Outdated Show resolved Hide resolved
JsonConverter now uses span parsing path so tests added to verify this works.
@Romanx Romanx force-pushed the feature/span-parsable-grain-ids branch from 3024268 to 79adcab Compare August 2, 2023 13:42
@Romanx Romanx marked this pull request as ready for review August 2, 2023 13:42
@Romanx
Copy link
Contributor Author

Romanx commented Aug 2, 2023

@gfoidl Added tests for the ISpanParsable members and also for the JsonConverter on the GrainId since I changed that to use the new faster ISpanParsable overload and there wasn't any tests.

Not sure if the tests are in the right place but it seemed like the best fit. If not I'm happy to move them.

@Romanx Romanx mentioned this pull request Aug 2, 2023
Copy link
Member

@gfoidl gfoidl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me the tests seem fine, but I'll let @ReubenBond decide on this.

? checked((int)reader.ValueSequence.Length)
: reader.ValueSpan.Length;

Span<char> buf = stackalloc char[valueLength];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • perf-wise stack allocation to a constant (and then slicing) is faster than using a variable -- especially if [SkipLocalsInit] is used, as then it's essentially only a (stack) pointer-move + the stack-cookie as safety guard
  • valueLength could be large enough to get a stack overflow, so we take any measures against this in that public api

Thus I'd write this as

Span<char> buf = valueLength <= 128
    ? (stackalloc char[128]).Slice(0, valueLength)
    : new char[valueLength];

The allocation of the char-array will be on the cold-path, but we get safety for potential stack overflows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good I'll make that change now, I can see this could be a problem if we get a large GrainId keyed value so the allocation is probably sensible to avoid a stack overflow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the allocation is probably sensible to avoid a stack overflow

Exactly.
There could also be some malicious code that produces large valueLengths, so DoS could happen, etc.

When we assume that valueLength is quite often > 128, so the threshold could be 256 or instead of allocating the char-array one could be rented from the ArrayPool<char>. But I think the length will be rather short, so that allocation is OK, as it's only on the rare taken path which acts as security measure against SO.

Avoids possible stack overflow and speed in the hot path
@@ -97,45 +98,56 @@ public void GrainIdShouldEncodeAndDecodePrimaryKeyGuidCorrectly()
}
}

[Fact, TestCategory("SlowBVT"), TestCategory("Identifiers")]
public void GrainId_ToFromPrintableString()
[Theory, TestCategory("SlowBVT"), TestCategory("Identifiers")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why we put these (obviously quick) tests in SlowBVT

@ReubenBond ReubenBond merged commit 3a14313 into dotnet:main Aug 3, 2023
19 checks passed
@ReubenBond
Copy link
Member

ReubenBond commented Aug 3, 2023

@Romanx are you running 7.x in production at the moment and is this impacting performance for you? If so, we can create a new release.

@Romanx
Copy link
Contributor Author

Romanx commented Aug 3, 2023

We are running 7.x in production but it's not impacting performance. I was writing a library that wraps over GrainId and wanted to parse it and had a span so noticed this and thought it'd be a nice improvement 👍

@Romanx Romanx deleted the feature/span-parsable-grain-ids branch August 3, 2023 15:53
@github-actions github-actions bot locked and limited conversation to collaborators Dec 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants